#include <algorithm>
#include "pocketrefine.h"
#include "../contour/mcconextractor.h"

using namespace PBVP;

PocketRefine::PocketRefine(GeometryData *protein, Reg3DVolumeData* pocketFunc)
{
	DistanceTransform *pDisTran = new DistanceTransform(protein);
	m_pProteinSDF = pDisTran->computeSDF();
	delete pDisTran;
	m_pPocketFunc = pocketFunc;
}

PocketRefine::PocketRefine(Reg3DVolumeData* sdf, Reg3DVolumeData* pocketFunc)
{
	m_pProteinSDF = new Reg3DVolumeData(sdf);
	m_pPocketFunc = pocketFunc;
}

PocketRefine::~PocketRefine()
{
	delete m_pProteinSDF;
}

/// 
GeometryData* PocketRefine::refinePocket(GeometryData *pocket, float eps)
{
	GeometryData *surf;
	DistanceTransform *pDisTran = new DistanceTransform(pocket);
	// compute SDF for the pocket envelop
	Reg3DVolumeData *pPocketSDF = pDisTran->computeSDF();
	delete pDisTran;
	for(int i = 0; i < pPocketSDF->numOfVerts(); i++) {
		// f1 is positive outside the pocket envelop, and negative inside
		float f1 = -pPocketSDF->getValue(i);
		float coord[3];
		pPocketSDF->getCoordinates(coord, i);
		float f2 = -m_pProteinSDF->getValue(coord);
		// set the new SDF value so that it wouldn't penetrate the protein surface
		f1 = std::max(f1-eps, f2);
		// set the new SDF value
		float f3 = m_pPocketFunc->getValue(coord);
		f1 = std::max(f1, -f3);

		pPocketSDF->setValue(f1, i);
	}
	MCContourExtractor* pMCContour = new MCContourExtractor();
	surf = pMCContour->extractContour(pPocketSDF, 0.0f);
	delete pMCContour;
	delete pPocketSDF;
	return surf;
}
